package com.p2p.Androidp2p;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;


public class AndroidP2P extends Activity{

    // Media player used to play files.
    MediaPlayer mp;
    //user name
    private static String username = "no name";
    //server Socket for all connections on server
    private ServerSocket sock = null;
    private static TableLayout theListView;
    private static Context theContext;
    private static int switcher = 0;
    //enums for switcher
    private final static int DOWNLOAD_PROGRESS = 2;
    private final int FILE_LIST = 1;
    private final int SEARCH = 3;
    private static ListView lv = null;


    public static Handler progressUpdater = new Handler() {

	public void handleMessage(Message m) {
	    if(switcher == DOWNLOAD_PROGRESS)
	    {
		theListView.requestFocus();
		theListView.bringToFront();
		theListView.setStretchAllColumns(true); 

		if (theListView.findViewWithTag(m.obj) == null) {
		    TableRow oneRow = new TableRow(theContext);
		    oneRow.setPadding(1, 5, 1, 5);
		    oneRow.setTag(m.obj);
		    
		    TextView nameView = new TextView(theContext);
		    nameView.setText(((Clientp2p)m.obj).filename);
		    
		    LayoutInflater inflater = (LayoutInflater)theContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		    
		    RelativeLayout theProgressLayout =  ((RelativeLayout) inflater.inflate(R.layout.progressbar, null));
		    ProgressBar progressBar = (ProgressBar) theProgressLayout.getChildAt(0);

		    progressBar.setMax(100); 
		    progressBar.setIndeterminate(false);
		    progressBar.setProgressDrawable(theContext.getResources().getDrawable(android.R.drawable.progress_horizontal));
		    progressBar.setBackgroundResource(android.R.drawable.progress_horizontal);

		    progressBar.setId(1213);
		    
		    oneRow.addView(nameView);
		    oneRow.addView(theProgressLayout);
		    
		    theListView.addView(oneRow);
		}
		else {
		    //Update progress bar
		    TableRow theRow = (TableRow) theListView.findViewWithTag(m.obj);
		    ProgressBar progressBar = (ProgressBar) theRow.findViewById(1213);
		    progressBar.setProgress((int) ((Clientp2p)m.obj).percentFinished);
		}
	    }
	}
    };

    /**
     * gets the id of the device that will be used as the user name
     * 
     */
    public void getDeviceId()
    {
	Context temp = AndroidP2P.this;
	TelephonyManager tMger = (TelephonyManager) temp.getSystemService(Context.TELEPHONY_SERVICE);
	username = tMger.getDeviceId();
    }

    /**
     * getter for user name
     * @return user name
     */
    static String getUsername()
    {
	return username;
    }
    
    /** 
     * Activate Menu key
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu){
	MenuInflater inf = getMenuInflater();
	inf.inflate(R.menu.menu, menu);
	return true;
    }

    /**
     * Handle option menu
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item){
	switch(item.getItemId()){
	    case R.id.Mdown:
		switcher = DOWNLOAD_PROGRESS;
		lv.setVisibility(View.INVISIBLE);
		theListView.setVisibility(View.VISIBLE);
		return true;
	    case R.id.Mshare:
		showShare();
		Toast.makeText(this, "share file", Toast.LENGTH_SHORT).show();
		return true;  
	    case R.id.exit:
		Builder adb = new AlertDialog.Builder(AndroidP2P.this);
		adb.setMessage("Do you want to exit?");
		adb.setPositiveButton("Yes", new DialogInterface.OnClickListener()
		{    
		    @Override
		    public void onClick(DialogInterface arg0, int arg1)
		    {
			Toast.makeText(AndroidP2P.this, "EXIT", Toast.LENGTH_SHORT).show();	
			finish();
		    }
		});
		adb.setNegativeButton("No", null);//if No, do nothing
		adb.show();
		return true;

	}
	return true;
    }


    // Listener objects for button presses.
    // (for now, when a button pressed it should just show "you pressed the x button")
    // (only exception to this is the search button which should also print the text contained in the search box)

    private ArrayList<HashMap<String, String>> convertMap(ArrayList<HashMap<String, String>> list)
    {
	ArrayList<HashMap<String, String>> newList = new ArrayList<HashMap<String, String>>();
	HashMap<String, String> newEntry = new HashMap<String, String>();
	HashMap<String, String> temp = null;

	//add first entry into new list
	newEntry.put("filename", "File Name");
	newEntry.put("size", "Size(MB)");
	newList.add(newEntry);

	newEntry = new HashMap<String, String>();
	int index = 1;
	int listSize = list.size();
	while(index < listSize)
	{
	    temp = list.get(index);
	    index++;
	    newEntry.put("filename", temp.get("filename"));

	    //truncate size to make it look better
	    double size = Double.valueOf(temp.get("size"));
	    DecimalFormat df = new DecimalFormat("0.#");
	    size = size/1000000;
	    String newSize = df.format(size);

	    newEntry.put("size", newSize);
	    newList.add(newEntry);
	    newEntry = new HashMap<String, String>();
	}

	return newList;
    }

    // Listens for presses of the Search button.
    private OnClickListener mSearchListener = new OnClickListener() {
	public void onClick(View v) {
	    switcher = SEARCH;
	    lv.setVisibility(View.VISIBLE);
	    theListView.setVisibility(View.INVISIBLE);
	    showSearch();
	}
    };
    
    // Listens for presses of the Shared button.
    private OnClickListener mSharedListener = new OnClickListener() {
	public void onClick(View v) {
	    switcher = FILE_LIST;
	    lv.setVisibility(View.VISIBLE);
	    theListView.setVisibility(View.INVISIBLE);
	    showShare();
	}

    };
    
    private void showSearch(){
	// Get the text from the text box (the search query).
	EditText et = (EditText)findViewById(R.id.search_box);
	String searchQuery = et.getText().toString();

	final ArrayList<HashMap<String, String>> fileList = Peer.searchFileList(searchQuery);
	ArrayList<HashMap<String, String>> displayList = convertMap(fileList);

	SimpleAdapter files = new SimpleAdapter(AndroidP2P.this, displayList, R.layout.search_list,
		new String[] {"filename", "size"}, new int[] {R.id.file_name, R.id.file_size});

	lv.setAdapter(files);		

	//deals with the clicking of button
	lv.setOnItemClickListener(new OnItemClickListener() 
	{
	    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
	    {
		if(position != 0 && switcher == SEARCH){//position 0 should not do anything 

		    Builder adb = new AlertDialog.Builder(AndroidP2P.this);

		    HashMap<String, String> entry = fileList.get(position);
		    final String[] hList = Peer.searchHolderList(entry.get("id"));
		    final int size = Integer.valueOf(entry.get("size"));
		    final int port = Integer.valueOf(hList[2]);
		    final String filename = entry.get("filename");
		    final String checksum = entry.get("checksum");

		    adb.setMessage(" Download file " + filename + "? " );

		    //if yes is clicked, start download
		    adb.setPositiveButton("Yes", new DialogInterface.OnClickListener()
		    {    
			@Override
			public void onClick(DialogInterface arg0, int arg1)
			{
			    Peer.startClient(hList[1], size, port, filename, checksum);
			}
		    });
		    adb.setNegativeButton("No", null);//if No, do nothing
		    adb.show();
		}
	    }    
	});	
    }
    
    private void showShare(){
	final ListView lv = (ListView)findViewById(R.id.results_list);

	ArrayAdapter<String> files = new ArrayAdapter<String>(AndroidP2P.this,R.layout.listview_layout);

	// Grab a list of all files in the Shared folder.
	File sdCard = new File(Environment.getExternalStorageDirectory().getPath() + "/Shared");
	File[] sharedFiles = sdCard.listFiles();

	if(sharedFiles != null)
	{
	    // Add each file in sharedFiles to the ArrayAdapter
	    for(int i = 0; i < sharedFiles.length; ++i)
	    {
		files.add(sharedFiles[i].getName());			    
	    }
	}
	else
	{
	    // If sharedFiles == null, there are no files.  Let the user know instead of leaving the ListView blank.
	    files.add("Your Shared folder contains no files!");
	}

	lv.setAdapter(files);

	// When an item is selected, try to play it with the media player.
	lv.setOnItemClickListener(new OnItemClickListener() 
	{
	    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
	    {
		if(switcher != FILE_LIST)
		{
		    return;
		}
		else
		{
		    String fileName = lv.getItemAtPosition(position).toString();

		    // Put together a path to the file.
		    String playFile = Environment.getExternalStorageDirectory().getPath() + "/Shared/" + fileName;

		    // Play the file.
		    try
		    {
			// Stop any currently playing file.
			mp.stop();
			mp.reset();		

			// Play the new file.
			mp.setDataSource(playFile);
			mp.prepare();
			mp.start();
		    }
		    catch(Exception e)
		    {
			Toast.makeText(AndroidP2P.this, "Could not play the file!", Toast.LENGTH_LONG).show();		
		    }
		}
	    }
	});
    }

    /**
     * sets finished to true when onDestroy() is called
     */
    public void onDestroy()
    {
	try
	{
	    sock.close();
	}
	catch (IOException e)
	{
	    Log.d("ANDROIDP2P S:onDestro()", e.getMessage());
	}
	super.onDestroy();
    }


    /** Called when the activity is first created. */
    public void onCreate(Bundle savedInstanceState) {

	super.onCreate(savedInstanceState);
	setContentView(R.layout.start_screen);

	theContext = AndroidP2P.this;

	// Associate the buttons with their appropriate listener objects.
	registerButtonListeners();

	//checks to see if the Shared folder is made yet, else it creates it
	File sdCard = Environment.getExternalStorageDirectory();
	File Shared = new File(sdCard,"Shared");
	Shared.mkdir();

	// Register the ListView for a context menu.
	lv = (ListView)findViewById(R.id.results_list);
	registerForContextMenu(lv);
	theListView = (TableLayout)findViewById(R.id.progressTable);

	// Instantiate the Media Player
	mp = new MediaPlayer();

	//gets device id and updates database
	getDeviceId();
	doUpdate();
	//starts server side
	startServer();
	EditText etr; 
	
	//Do same thing as hitting search key if enter key is pressed 
	etr = (EditText)findViewById(R.id.search_box);
	etr.setOnKeyListener(new OnKeyListener() {
	    @Override
	    public boolean onKey(View v, int keyCode, KeyEvent event)
	    {
		if(keyCode == KeyEvent.KEYCODE_ENTER){
		    Toast.makeText(AndroidP2P.this, "ENTER!!", Toast.LENGTH_SHORT).show();
		    switcher = SEARCH;
		    lv.setVisibility(View.VISIBLE);
		    theListView.setVisibility(View.INVISIBLE);
		    showSearch();  
		    return true;
		}
		return false;
	    }  
	});
	
    }

    /**
     * runs peer.update and prints a message on the screen if it succeeded or failed
     */
    public void doUpdate()
    {
	int ret = Peer.update();
	if(ret == 0)
	{
	    return;
	}
	else
	{
	    Toast.makeText(AndroidP2P.this, "Error on Update", Toast.LENGTH_SHORT).show();

	}
    }

    /**
     * server thread code
     */
    private void startServer()
    {
	try
	{
	    sock = new ServerSocket(3400);
	}
	catch (IOException e)
	{
	    Log.d("ANDROIDP2P S:startServer", e.getMessage());
	}
	ServerHandler server = new ServerHandler(sock);
	Thread serverHandler = new Thread(server);
	serverHandler.start();
    }
    /**
     * a function for registering buttons 
     */
    private void registerButtonListeners()
    {
	// Find each button using the ids declared in the xml layout file (id is declared using the android:id attribute).
	// Then, associate that button object with the corresponding listener object.
	Button searchButton = (Button)findViewById(R.id.search_main);
	searchButton.setOnClickListener(mSearchListener);

    }

    /**
     * Create context menu 
     * @param
     * 
     */
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo cmi)
    {
	if(switcher == FILE_LIST)
	{
	    menu.add(0,0,0,"Delete");
	    menu.add(0,1,0,"Rename");
	    menu.add(0,2,0,"Play");
	    menu.add(0,3,0,"Stop playback");
	}
    }
    /**
     * Handle each context menu properly when it is clicked
     */
    public boolean onContextItemSelected(MenuItem item)
    {
	if(switcher != FILE_LIST)
	{
	    return false;
	}
	
	final AdapterContextMenuInfo cmi = (AdapterContextMenuInfo)item.getMenuInfo();
	int id = item.getItemId();

	if(id == 0)
	{	    
	    // Get the name of the chosen file.
	    String fileName = lv.getAdapter().getItem(cmi.position).toString();

	    // Put together a path to the file.
	    File delFile = new File(Environment.getExternalStorageDirectory().getPath() + "/Shared/" + fileName);
	    boolean success = delFile.delete();
	    if(success)
	    {
		Toast.makeText(AndroidP2P.this, "Successfully deleted " + fileName, Toast.LENGTH_SHORT).show();
	    }
	    else
	    {
		Toast.makeText(AndroidP2P.this, "Error deleting file!", Toast.LENGTH_SHORT).show();
	    }

	    // Update the listView to remove the deleted file (simulate another click of the Shared button).
	    mSharedListener.onClick(null);

	}
	else if(id == 1)
	{
	    AlertDialog.Builder alert = new AlertDialog.Builder(this);  

	    alert.setTitle("Rename file");  
	    alert.setMessage("New file name:");  

	    // Set an EditText view to get user input   
	    final EditText input = new EditText(this);  
	    alert.setView(input);  

	    alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {  
		public void onClick(DialogInterface dialog, int whichButton) {

		    // Get the (original) name of the chosen file.
		    String fileName = lv.getAdapter().getItem(cmi.position).toString();

		    // Put together a path to the file.
		    File oldFile = new File(Environment.getExternalStorageDirectory().getPath() + "/Shared/" + fileName);

		    // Put together the desired new path.
		    File newFile = new File(Environment.getExternalStorageDirectory().getPath() + "/Shared/" + input.getText().toString());

		    boolean success = oldFile.renameTo(newFile);
		    if(success)
		    {
			Toast.makeText(AndroidP2P.this, "Successfully renamed file!", Toast.LENGTH_LONG).show();
		    }
		    else
		    {
			Toast.makeText(AndroidP2P.this, "Error renaming file!", Toast.LENGTH_LONG).show();		  
		    }

		    // Simulate a click of the Shared button to update the file list.
		    mSharedListener.onClick(null);
		}  
	    });  

	    alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {  
		public void onClick(DialogInterface dialog, int whichButton) {  
		    Toast.makeText(AndroidP2P.this, "Rename cancelled!", Toast.LENGTH_LONG).show(); 
		}  
	    });

	    alert.show();	      
	}
	else if(id == 2)
	{
	    // Get the name of the chosen file.
	    String fileName = lv.getAdapter().getItem(cmi.position).toString();

	    // Put together a path to the file.
	    String playFile = Environment.getExternalStorageDirectory().getPath() + "/Shared/" + fileName;

	    // Play the file.
	    try
	    {
		// Stop any currently playing file.
		mp.stop();
		mp.reset();		

		// Play the new file.
		mp.setDataSource(playFile);
		mp.prepare();
		mp.start();
	    }
	    catch(Exception e)
	    {
		Toast.makeText(AndroidP2P.this, "Could not play the file!", Toast.LENGTH_LONG).show();		
	    }	    
	}
	else if(id == 3)
	{
	    // Stop any playback, even if selected from a different file.
	    mp.stop();	    
	}

	return true;
    }

}